#include "GlassConsole.h"

///Copyright (c) 2009-2010 T. Klepzig 


BOOL GlassConsole::dwmActive=false;
WMCallback * GlassConsole::wmCallback=0;
HWINEVENTHOOK GlassConsole::hWinEventHook=0;
set<GlassConsole*> GlassConsole::instances;


GlassConsole::GlassConsole(HINSTANCE hInstance)
{
	if (instances.empty())
	{
		hWinEventHook=SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW,0,WinEventProc,0,0,0);

		wmCallback=new WMCallback(hInstance);
		wmCallback->OnWmCallback(WndProc);

		DwmIsCompositionEnabled(&dwmActive);
	}

	instances.insert(this);
}

GlassConsole::~GlassConsole()
{	
	Deactivate();

	instances.erase(this);

	if (instances.empty())
	{
		UnhookWinEvent(hWinEventHook);
		delete wmCallback;
	}
}

CCState GlassConsole::Activate()
{
	CCState result;
	if ((result = CassiopeiaComponent::Activate()) != CCState::Successful)
		return result;

	if (dwmActive)
		EnumWindows(EnumWindowsProc,TRUE);

	return CCState::Successful;
}

CCState GlassConsole::Deactivate()
{
	CCState result;
	if ((result = CassiopeiaComponent::Deactivate()) != CCState::Successful)
		return result;

	if (dwmActive)
		EnumWindows(EnumWindowsProc,FALSE);

	return CCState::Successful;
}

void GlassConsole::RemoveGlassFromConsoleWindow(HWND hWnd)
{
	if (!this->IsActive())
		return;

	TCHAR className[_MAX_PATH]={0};
	GetClassName(hWnd,className,sizeof(className));

	if (!_tcscmp(className,TEXT("ConsoleWindowClass")))
	{
		MARGINS margins = {0,0,0,0};
		DwmExtendFrameIntoClientArea(hWnd,&margins);
	}
}

void GlassConsole::ExtendGlassIntoConsoleWindow(HWND hWnd)
{
	if (!this->IsActive())
		return;

	TCHAR className[_MAX_PATH]={0};
	GetClassName(hWnd,className,sizeof(className));

	if (!_tcscmp(className,TEXT("ConsoleWindowClass")))
	{
		MARGINS margins = {-1,-1,-1,-1};
		DwmExtendFrameIntoClientArea(hWnd,&margins);
	}
}

BOOL CALLBACK GlassConsole::EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
	if (Utilities::IsValidTaskWindow(hWnd))
	{
		if (lParam == TRUE)
		{
			set<GlassConsole*>::iterator iter;
			for(iter=instances.begin(); iter!=instances.end(); iter++)
			{
				(*iter)->ExtendGlassIntoConsoleWindow(hWnd);
			}
		}
		else if (lParam == FALSE)
		{
			set<GlassConsole*>::iterator iter;
			for(iter=instances.begin(); iter!=instances.end(); iter++)
			{
				(*iter)->RemoveGlassFromConsoleWindow(hWnd);
			}
		}
	}

	return true;
}



VOID CALLBACK GlassConsole::WinEventProc(HWINEVENTHOOK hWinEventHook,DWORD dwEvent,HWND hWnd,LONG idObject,LONG idChild,DWORD idEventThread,DWORD dwmsEventTime)
{
	if (dwEvent == EVENT_OBJECT_SHOW && idObject == OBJID_WINDOW)
	{
		if (Utilities::IsValidTaskWindow(hWnd) && dwmActive)
		{
			set<GlassConsole*>::iterator iter;
			for(iter=instances.begin(); iter!=instances.end(); iter++)
			{
				(*iter)->ExtendGlassIntoConsoleWindow(hWnd);
			}
		}
	}
}


LRESULT CALLBACK GlassConsole::WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DWMCOMPOSITIONCHANGED:
		{
			BOOL dwmEnabled;
			DwmIsCompositionEnabled(&dwmEnabled);

			dwmActive = dwmEnabled;

			if (dwmActive)
				EnumWindows(EnumWindowsProc,TRUE);

			break;
		}
	}

	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
